#include "analog_clock.h"
#include <math.h>
#include "fonts.h"

void drawAnalogClock(Panel& panel,
                     uint16_t posX,
                     uint16_t posY,
                     uint16_t w,
                     uint16_t h,
                     uint8_t hour,
                     uint8_t minute,
                     uint8_t second,
                     const char* weekDayStr,
                     int year,
                     int month,
                     int day) {
    // compute center and radius inside bounding box
    uint16_t cx = posX + w / 2;
    uint16_t cy = posY + h / 2;
    uint16_t radius = (w < h ? w : h) / 2;
    if (radius > 2) radius -= 2;  // small margin

    // clear the clock area
    if (w > 0 && h > 0) {
        panel.fillRect(posX, posY, posX + w - 1, posY + h - 1, 0, 0, 0);
    }

    // draw outer circle
    panel.drawCircle(cx, cy, radius, 255, 255, 0);

    // draw hour ticks (25% shorter)
    for (int i = 0; i < 12; i++) {
        float angle = (i * 30.0f) * M_PI / 180.0f;  // degrees to radians
        int16_t sx = cx + (int16_t)((radius - 4) * cos(angle));
        int16_t sy = cy + (int16_t)((radius - 4) * sin(angle));
        int16_t ex = cx + (int16_t)(radius * cos(angle));
        int16_t ey = cy + (int16_t)(radius * sin(angle));
        panel.drawLine(sx, sy, ex, ey, 255, 255, 0);
    }

    // Draw week day string at the midpoint between 12 o'clock and the center, using a narrow 5x8 font
    if (weekDayStr) {
        uint8_t textLen = 0;
        for (const char* p = weekDayStr; *p; ++p)
            ++textLen;
        uint8_t charSpacing = 1;
        uint8_t textWidth = (5 + charSpacing) * textLen - charSpacing;
        uint8_t textHeight = 8;
        int16_t midY = (cy - radius + cy) / 2;
        int16_t textX = cx - textWidth / 2;
        int16_t textY = midY - textHeight / 2;
        for (uint8_t i = 0; i < textLen; ++i) {
            int idx = fontIndex(weekDayStr[i]);
            for (uint8_t row = 0; row < 8; ++row) {
                uint8_t bits = font5x8[idx][row];
                for (uint8_t col = 0; col < 5; ++col) {
                    if (bits & (1 << (4 - col))) {
                        panel.drawPixel(textX + i * (5 + charSpacing) + col, textY + row, 0, 100, 0);
                    }
                }
            }
        }
    }

    // Draw date string below the center, between center and 6 o'clock
    char dateStr[12] = "";
    if (year > 0 && month > 0) {
        snprintf(dateStr, sizeof(dateStr), "%04d-%02d", year, month);
    } else {
        // fallback: unknown date -> escaped question marks to avoid trigraph warnings
        snprintf(dateStr, sizeof(dateStr), "\?\?\?\?-\?\?");
    }
    uint8_t dateLen = 0;
    for (const char* p = dateStr; *p; ++p)
        ++dateLen;
    uint8_t charSpacing = 1;
    uint8_t dateWidth = (5 + charSpacing) * dateLen - charSpacing;
    uint8_t dateHeight = 8;
    int16_t midY2 = (cy + (cy + radius)) / 2;
    int16_t dateX = cx - dateWidth / 2;
    int16_t dateY = midY2 - dateHeight / 2;
    for (uint8_t i = 0; i < dateLen; ++i) {
        int idx = fontIndex(dateStr[i]);
        for (uint8_t row = 0; row < 8; ++row) {
            uint8_t bits = font5x8[idx][row];
            for (uint8_t col = 0; col < 5; ++col) {
                if (bits & (1 << (4 - col))) {
                    panel.drawPixel(dateX + i * (5 + charSpacing) + col, dateY + row, 0, 100, 0);
                }
            }
        }
    }

    // Draw day of month (D) at the midpoint between center and 9 o'clock, using a 1.5x scaled 5x8 font, white color
    // day of month comes from parameter if provided
    int dayVal = (day > 0) ? day : 1;
    // Only show one digit if day < 10
    char dayStr[3];
    if (dayVal < 10) {
        snprintf(dayStr, sizeof(dayStr), "%d", dayVal);
    } else {
        snprintf(dayStr, sizeof(dayStr), "%02d", dayVal);
    }
    uint8_t numDigits = (day < 10) ? 1 : 2;
    // Use the same 5x8 font as other text
    // Midpoint between center and 9 o'clock
    int16_t midX_day = (cx + (cx - radius)) / 2;
    float scale = 1.5f;
    uint8_t charW = 5 * scale;
    uint8_t charH = 8 * scale;
    // Increase spacing between digits
    uint8_t charSpacingDay = 3 * scale;  // slightly larger spacing
    uint8_t dayWidth = (charW + charSpacingDay) * numDigits - charSpacingDay;
    int16_t dayX = midX_day - dayWidth / 2;
    // Align vertical center of date with vertical center of panel
    int16_t dayY = cy - charH / 2;
    for (uint8_t i = 0; i < numDigits; ++i) {
        int idx = fontIndex(dayStr[i]);
        for (uint8_t row = 0; row < 8; ++row) {
            uint8_t bits = font5x8[idx][row];
            for (uint8_t col = 0; col < 5; ++col) {
                if (bits & (1 << (4 - col))) {
                    // 1.5x scale: draw 3x2 block for each pixel
                    int px = dayX + i * (charW + charSpacingDay) + col * scale;
                    int py = dayY + row * scale;
                    // Draw 3x2 block (approximate 1.5x)
                    panel.drawPixel(px, py, 0, 100, 0);
                    panel.drawPixel(px + 1, py, 0, 100, 0);
                    panel.drawPixel(px + 2, py, 0, 100, 0);
                    panel.drawPixel(px, py + 1, 0, 100, 0);
                    panel.drawPixel(px + 1, py + 1, 0, 100, 0);
                    panel.drawPixel(px + 2, py + 1, 0, 100, 0);
                }
            }
        }
    }

    // Draw hands in foreground so they appear on top of all elements
    // compute angles for hands (0 at 12 o'clock, increasing clockwise)
    float hourAngle = ((hour % 12) + minute / 60.0f) * 30.0f * M_PI / 180.0f;
    float minuteAngle = minute * 6.0f * M_PI / 180.0f;
    float secondAngle = second * 6.0f * M_PI / 180.0f;

    // draw hour hand (thicker - 3 pixels)
    int16_t hx = cx + (int16_t)((radius * 0.5f) * sin(hourAngle));
    int16_t hy = cy - (int16_t)((radius * 0.5f) * cos(hourAngle));
    panel.drawLine(cx, cy, hx, hy, 255, 0, 0);
    // Draw second parallel line for thickness
    int16_t hx2 = cx + (int16_t)((radius * 0.5f) * sin(hourAngle)) + (int16_t)(cos(hourAngle) * 1);
    int16_t hy2 = cy - (int16_t)((radius * 0.5f) * cos(hourAngle)) + (int16_t)(sin(hourAngle) * 1);
    panel.drawLine(cx, cy, hx2, hy2, 255, 0, 0);
    // Draw third parallel line for thickness
    int16_t hx3 = cx + (int16_t)((radius * 0.5f) * sin(hourAngle)) - (int16_t)(cos(hourAngle) * 1);
    int16_t hy3 = cy - (int16_t)((radius * 0.5f) * cos(hourAngle)) - (int16_t)(sin(hourAngle) * 1);
    panel.drawLine(cx, cy, hx3, hy3, 255, 0, 0);

    // draw minute hand (now yellow, thicker - 3 pixels)
    int16_t mx = cx + (int16_t)((radius * 0.7f) * sin(minuteAngle));
    int16_t my = cy - (int16_t)((radius * 0.7f) * cos(minuteAngle));
    panel.drawLine(cx, cy, mx, my, 255, 255, 0);
    // Draw second parallel line for thickness
    int16_t mx2 = cx + (int16_t)((radius * 0.7f) * sin(minuteAngle)) + (int16_t)(cos(minuteAngle) * 1);
    int16_t my2 = cy - (int16_t)((radius * 0.7f) * cos(minuteAngle)) + (int16_t)(sin(minuteAngle) * 1);
    panel.drawLine(cx, cy, mx2, my2, 255, 255, 0);
    // Draw third parallel line for thickness
    int16_t mx3 = cx + (int16_t)((radius * 0.7f) * sin(minuteAngle)) - (int16_t)(cos(minuteAngle) * 1);
    int16_t my3 = cy - (int16_t)((radius * 0.7f) * cos(minuteAngle)) - (int16_t)(sin(minuteAngle) * 1);
    panel.drawLine(cx, cy, mx3, my3, 255, 255, 0);

    // draw second hand (blue), 4 pixels below hour hand end, thicker - 3 pixels
    int16_t sx = cx + (int16_t)((radius * 0.9f) * sin(secondAngle));
    int16_t sy = cy - (int16_t)((radius * 0.9f) * cos(secondAngle)) + 4;
    panel.drawLine(cx, cy, sx, sy, 0, 0, 255);
    // Draw second parallel line for thickness
    int16_t sx2 = cx + (int16_t)((radius * 0.9f) * sin(secondAngle)) + (int16_t)(cos(secondAngle) * 1);
    int16_t sy2 = cy - (int16_t)((radius * 0.9f) * cos(secondAngle)) + (int16_t)(sin(secondAngle) * 1) + 4;
    panel.drawLine(cx, cy, sx2, sy2, 0, 0, 255);
    // Draw third parallel line for thickness
    int16_t sx3 = cx + (int16_t)((radius * 0.9f) * sin(secondAngle)) - (int16_t)(cos(secondAngle) * 1);
    int16_t sy3 = cy - (int16_t)((radius * 0.9f) * cos(secondAngle)) - (int16_t)(sin(secondAngle) * 1) + 4;
    panel.drawLine(cx, cy, sx3, sy3, 0, 0, 255);

    // Draw AM/PM in the middle between center and 3 o'clock, vertically centered, using 5x8 font like weekday
    const char* ampmStr = (hour < 12) ? "AM" : "PM";
    uint8_t textLen = 2;
    uint8_t charSpacingAmpm = 1;
    uint8_t textWidth = (5 + charSpacingAmpm) * textLen - charSpacingAmpm;
    uint8_t textHeight = 8;
    int16_t ax = cx + radius / 2 - textWidth / 2;
    int16_t ay = cy - textHeight / 2;
    for (uint8_t i = 0; i < textLen; ++i) {
        int idx = fontIndex(ampmStr[i]);
        for (uint8_t row = 0; row < 8; ++row) {
            uint8_t bits = font5x8[idx][row];
            for (uint8_t col = 0; col < 5; ++col) {
                if (bits & (1 << (4 - col))) {
                    panel.drawPixel(ax + i * (5 + charSpacingAmpm) + col, ay + row, 0, 100, 0);
                }
            }
        }
    }
}
